#include <iostream>
#include <poll.h>
#include "Socket.hpp"
#include <memory>
class PollServer
{
    static const int size = 1024;
    static const int defaultfd = -1;

public:
    PollServer(uint16_t port) : _poll(std::make_unique<TcpSocket>()), _isruning(false)
    {
        _poll->BuildTcpSocketServer(port); // 构建服务器
        // 初始化数组
        for (int i = 0; i < size; i++)
        {
            _fds[i].fd = defaultfd;
            _fds[i].events = 0;
            _fds[i].revents = 0;
        }
        _fds[0].fd = _poll->Fd();
        _fds[0].events = POLLIN;
    }
    void Start()
    {
        _isruning = true;
        int timeout = -1;
        while (_isruning)
        {
            int n = poll(_fds, size, timeout);
            switch (n)
            {
            case 0:
                LOG(LogLevel::DEBUG) << "timewait out...";
                break;
            case -1:
                LOG(LogLevel::FATAL) << "poll false";
                break;
            default:
                // 分配，准备好的fd可能是listenfd，也可能是普通fd
                Assignment();
                break;
            }
        }
    }
    // 将已就绪的分发到对应的处理区
    void Assignment()
    {
        for (int i = 0; i < size; i++)
        {
            if (_fds[i].fd == defaultfd)
                continue;
            if (_fds[i].revents == POLLIN)
            {
                if (_fds[i].fd == _poll->Fd())
                {
                    Accept();
                }
                else
                {
                    Recv(_fds[i].fd, i);
                }
            }
        }
    }

    // 建立连接
    void Accept()
    {
        InetAddr client;
        int sockfd = _poll->Accept(&client);
        if (sockfd < 0)
        {
            LOG(LogLevel::ERROR) << "accept false";
            return;
        }
        LOG(LogLevel::INFO) << "get a new link, sockfd: "
                            << sockfd << ", client is: " << client.GetName();
        int pos = 0;
        for (; pos < size; pos++)
        {
            if (_fds[pos].fd == defaultfd)
                break;
        }
        if (pos == size)
        {
            LOG(LogLevel::WARNING) << "poll server full";
            close(sockfd);
        }
        else
        {
            _fds[pos].fd = sockfd;
            _fds[pos].events = POLLIN;
            _fds[pos].revents = 0;
        }
    }
    // 进行读
    void Recv(int fd, int pos)
    {
        char buffer[1024];
        ssize_t size = recv(fd, buffer, sizeof(buffer) - 1, 0);
        if (size > 0)
        {
            buffer[size] = 0;
            std::cout << "client say@ " << buffer << std::endl;
        }
        else if (size == 0)
        {
            LOG(LogLevel::DEBUG) << "client quit";
            close(_fds[pos].fd);
            _fds[pos].fd = -1;
            _fds[pos].events = 0;
            _fds[pos].revents = 0;
        }
        else
        {
            LOG(LogLevel::FATAL) << "recv 异常";
            close(_fds[pos].fd);
            _fds[pos].fd = -1;
            _fds[pos].events = 0;
            _fds[pos].revents = 0;
        }
    }
    ~PollServer()
    {
    }

private:
    std::unique_ptr<Socket> _poll;
    bool _isruning;
    struct pollfd _fds[size];
};